﻿using System;
using Language.Utility;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.TextManager.Interop;
using Red.Scripts.Defines.Utilities;

namespace Red.Scripts.Legacy
{
    internal partial class LanguageInfo : IVsLanguageDebugInfo
    {
        #region IVsLanguageDebugInfo

        public int GetLanguageID( IVsTextBuffer pBuffer, int iLine, int iCol, out Guid pguidLanguageID )
        {
            pguidLanguageID = Red.Scripts.Defines.Guids.Language.Id.Guid;

            return VSConstants.S_OK;
        }

        public int GetLocationOfName( string pszName, out string pbstrMkDoc, TextSpan[] pspanLocation )
        {
            pbstrMkDoc = null;
            return VSConstants.E_NOTIMPL;
        }

        public int GetNameOfLocation( IVsTextBuffer pBuffer, int iLine, int iCol, out string pbstrName, out int piLineOffset )
        {
            pbstrName = null;
            piLineOffset = 0;
            return VSConstants.E_NOTIMPL;
        }

        public int GetProximityExpressions( IVsTextBuffer pBuffer, int iLine, int iCol, int cLines, out IVsEnumBSTR ppEnum )
        {
            ppEnum = null;
            return VSConstants.E_NOTIMPL;
        }

        public int IsMappedLocation( IVsTextBuffer pBuffer, int iLine, int iCol )
        {
            return VSConstants.E_NOTIMPL;
        }

        public int ResolveName( string pszName, uint dwFlags, out IVsEnumDebugName ppNames )
        {
            ppNames = null;
            return VSConstants.E_NOTIMPL;
        }

        public int ValidateBreakpointLocation( IVsTextBuffer pBuffer, int iLine, int iCol, TextSpan[] pCodeSpan )
        {
            IComponentModel componentModel = (IComponentModel)ServiceProvider.GlobalProvider.GetService( typeof( SComponentModel ) );

            int position;
            if ( pBuffer.GetPositionOfLineIndex( iLine, iCol, out position ) == VSConstants.S_OK )
            {
                IVsEditorAdaptersFactoryService adapter = componentModel.GetService<IVsEditorAdaptersFactoryService>();
                ITextBuffer textBuffer = adapter.GetDataBuffer( pBuffer );

                FilePath filepath = new FilePath() { Absolute = textBuffer.ExtractFilename() };

                Language.Stub.Database database = componentModel.GetService<Language.Stub.Database>();

                Language.Stub.File file;

                if( database.FileByPath.TryGetValue( filepath.Relative, out file ) )
                {
                    int index = file.Breakpoints.LowerBound( position );

                    if ( index >= 0 && index < file.Breakpoints.Count )
                    {
                        if ( pCodeSpan != null && pCodeSpan.Length > 0 )
                        {
                            Language.Stub.DetailedContext breakpoint = file.Breakpoints.Values[ index ];

                            pCodeSpan[ 0 ].iStartLine = breakpoint.Line;
                            pCodeSpan[ 0 ].iStartIndex = breakpoint.Position.Start - breakpoint.LineStart;

                            pCodeSpan[ 0 ].iEndLine = breakpoint.Line;
                            pCodeSpan[ 0 ].iEndIndex = breakpoint.Position.End - breakpoint.LineStart;
                        }

                        return VSConstants.S_OK;
                    }
                }
                else
                {
                    pCodeSpan[ 0 ].iStartLine = iLine;
                    pCodeSpan[ 0 ].iStartIndex = iCol;

                    pCodeSpan[ 0 ].iEndLine = iLine;
                    pCodeSpan[ 0 ].iEndIndex = iCol;


                    return VSConstants.E_PENDING;
                }
            }

            return VSConstants.S_FALSE;
        }

        #endregion IVsLanguageDebugInfo
    }
}
